<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<title>Pluralisation</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
		<meta name="viewport" content="width=device-width initial-scale=1">
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<meta http-equiv="Content-Language" content="en-gb">

<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
  var popup = document.getElementById(material_id);
  popup.classList.toggle("show");
}
</script>

<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
		
	</head>
	<body class="commentary-font">
		<nav role="navigation">
		<h1><a href="../index.html"><img src="../docs-assets/Inform.png" height=72> </a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=0> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="https://github.com/ganelson/inweb"><img src="../docs-assets/github.png" height=0> inweb</a></li>
<li><a href="https://github.com/ganelson/intest"><img src="../docs-assets/github.png" height=0> intest</a></li>
</ul>
		</nav>
		<main role="main">
		<!-- Weave of 'Pluralisation' generated by inweb -->
<div class="breadcrumbs">
    <ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../services.html">Services</a></li><li><a href="index.html">inflections</a></li><li><a href="index.html#2">Chapter 2: Simple Inflections</a></li><li><b>Pluralisation</b></li></ul></div>
<p class="purpose">To form plurals of nouns.</p>

<ul class="toc"><li><a href="2-plr.html#SP1">&#167;1. Dictionary</a></li><li><a href="2-plr.html#SP3">&#167;3. Searching the plural dictionary</a></li><li><a href="2-plr.html#SP4">&#167;4. The pluralizing trie</a></li></ul><hr class="tocbar">

<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Dictionary.</b>A modest dictionary of plurals is maintained to allow the user to record
better plurals than the ones we would make ourselves. This assumes that a
plural can be constructed without knowledge of context, but that works in
almost all cases. (Arguably "dwarf" should pluralise to "dwarfs" when
discussing stars and to "dwarves" when reading Tolkien, but it is devoutly
to be hoped that few works of IF will contain both at once.)
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">plural_dictionary_entry</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">NATURAL_LANGUAGE_WORDS_TYPE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">defined_in</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">singular_form</span><span class="plain-syntax">; </span><span class="comment-syntax"> words of singular form</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">plural_form</span><span class="plain-syntax">; </span><span class="comment-syntax"> words of plural form</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">plural_dictionary_entry</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure plural_dictionary_entry is accessed in 3/vc and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </b>Note that we are entirely allowed to register a new plural for a phrase
which already has a plural in the dictionary, even for the same language,
which is why we do not trouble to search the existing dictionary here.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Pluralisation::register</span><span class="plain-syntax">(</span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">S</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">NATURAL_LANGUAGE_WORDS_TYPE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nl</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">plural_dictionary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pde</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">plural_dictionary_entry</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">pde</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">singular_form</span><span class="plain-syntax"> = </span><span class="identifier-syntax">S</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">pde</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">plural_form</span><span class="plain-syntax"> = </span><span class="identifier-syntax">P</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">pde</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">defined_in</span><span class="plain-syntax"> = </span><span class="identifier-syntax">nl</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">CONSTRUCTED_PLURALS</span><span class="plain-syntax">, </span><span class="string-syntax">"[Registering plural of %W as %W]\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">S</span><span class="plain-syntax">, </span><span class="identifier-syntax">P</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. Searching the plural dictionary.</b>The following routine can either be called once only &mdash; in which case it
yields up the best known plural for the phrase &mdash; or iteratively, in which
case it serves up all known plurals of the given phrase, starting with the
best (the earliest defined in the text, if any plural for this phrase has
been so defined) and finishing up with the worst (a mechanically-made
one not found in the dictionary).
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">plural_dictionary_entry</span><span class="plain-syntax"> *</span><span class="function-syntax">Pluralisation::make</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Pluralisation::make</span></span>:<br/>Lexical Clusters - <a href="3-lc2.html#SP3_1">&#167;3.1</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> *</span><span class="identifier-syntax">PW</span><span class="plain-syntax">,</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">plural_dictionary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">search_from</span><span class="plain-syntax">, </span><span class="identifier-syntax">NATURAL_LANGUAGE_WORDS_TYPE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nl</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">nl</span><span class="plain-syntax"> = </span><a href="4-dl.html#SP1" class="function-link"><span class="function-syntax">DefaultLanguage::get</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nl</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">plural_dictionary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pde</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::empty</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) { *</span><span class="identifier-syntax">PW</span><span class="plain-syntax"> = </span><span class="identifier-syntax">EMPTY_WORDING</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; }</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">search_from</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">search_from</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FIRST_OBJECT</span><span class="plain-syntax">(</span><span class="reserved-syntax">plural_dictionary_entry</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">search_from</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NEXT_OBJECT</span><span class="plain-syntax">(</span><span class="identifier-syntax">search_from</span><span class="plain-syntax">, </span><span class="reserved-syntax">plural_dictionary_entry</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pde</span><span class="plain-syntax"> = </span><span class="identifier-syntax">search_from</span><span class="plain-syntax">; </span><span class="identifier-syntax">pde</span><span class="plain-syntax">; </span><span class="identifier-syntax">pde</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NEXT_OBJECT</span><span class="plain-syntax">(</span><span class="identifier-syntax">pde</span><span class="plain-syntax">, </span><span class="reserved-syntax">plural_dictionary_entry</span><span class="plain-syntax">))</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">pde</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">defined_in</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">pde</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">defined_in</span><span class="plain-syntax"> == </span><span class="identifier-syntax">nl</span><span class="plain-syntax">))</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::match</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">pde</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">singular_form</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">                *</span><span class="identifier-syntax">PW</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pde</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">plural_form</span><span class="plain-syntax">;</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">pde</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            }</span>

<span class="plain-syntax">    </span><span class="named-paragraph-container code-font"><a href="2-plr.html#SP3_1" class="named-paragraph-link"><span class="named-paragraph">Make a new plural by lexical writing back</span><span class="named-paragraph-number">3.1</span></a></span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3_1" class="paragraph-anchor"></a><b>&#167;3.1. </b>When the dictionary fails us, we use lexical rewriting to construct plurals
of phrases found only in the singular in the source. For instance, if the
designer says that "A wicker basket is a kind of container" then Inform will
need to recognise not only "wicker basket" but also "wicker baskets", a
pair of words not found in the source text anywhere. So the following
routine takes the text <span class="extract"><span class="extract-syntax">(w1, w2)</span></span> and feeds a suitable plural into the
lexer, emerging with the text <span class="extract"><span class="extract-syntax">(plw1, plw2)</span></span>.
</p>

<p class="commentary">We do not write the new plural into the dictionary: there is no need, as
it can be rebuilt quickly whenever needed again.
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Make a new plural by lexical writing back</span><span class="named-paragraph-number">3.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">feed_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">id</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Feeds::begin</span><span class="plain-syntax">();</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::length</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">) &gt; </span><span class="constant-syntax">1</span><span class="plain-syntax">) </span><span class="identifier-syntax">Feeds::feed_wording</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::trim_last_word</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">));</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">last_wn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Wordings::last_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">original</span><span class="plain-syntax">)</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">pluralised</span><span class="plain-syntax">)</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">original</span><span class="plain-syntax">, </span><span class="string-syntax">"%+W"</span><span class="plain-syntax">, </span><span class="identifier-syntax">Wordings::one_word</span><span class="plain-syntax">(</span><span class="identifier-syntax">last_wn</span><span class="plain-syntax">));</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (*(</span><span class="identifier-syntax">Lexer::word_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">last_wn</span><span class="plain-syntax">)) == </span><span class="character-syntax">'\"'</span><span class="plain-syntax">) </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">pluralised</span><span class="plain-syntax">, </span><span class="string-syntax">"some-long-text"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><a href="2-plr.html#SP4" class="function-link"><span class="function-syntax">Pluralisation::regular</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pluralised</span><span class="plain-syntax">, </span><span class="identifier-syntax">original</span><span class="plain-syntax">, </span><span class="identifier-syntax">nl</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">Feeds::feed_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">pluralised</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    *</span><span class="identifier-syntax">PW</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Feeds::end</span><span class="plain-syntax">(</span><span class="identifier-syntax">id</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">original</span><span class="plain-syntax">)</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">pluralised</span><span class="plain-syntax">)</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">CONSTRUCTED_PLURALS</span><span class="plain-syntax">, </span><span class="string-syntax">"[Constructing plural of %W as %W]\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">, *</span><span class="identifier-syntax">PW</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-plr.html#SP3">&#167;3</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. The pluralizing trie.</b>The following takes a single word, assumes it to be a noun which meaningfully
has a plural, and modifies it to the plural form.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Pluralisation::regular</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">Pluralisation::regular</span></span>:<br/><a href="2-plr.html#SP3_1">&#167;3.1</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">from</span><span class="plain-syntax">,</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">NATURAL_LANGUAGE_WORDS_TYPE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nl</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">nl</span><span class="plain-syntax"> = </span><a href="4-dl.html#SP1" class="function-link"><span class="function-syntax">DefaultLanguage::get</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nl</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">match_avinue</span><span class="plain-syntax"> *</span><span class="identifier-syntax">plural_trie</span><span class="plain-syntax"> =</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">PreformUtilities::define_trie</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;singular-noun-to-its-plural&gt;</span><span class="plain-syntax">, </span><span class="identifier-syntax">TRIE_END</span><span class="plain-syntax">,</span>
<span class="plain-syntax">            </span><a href="4-dl.html#SP1" class="function-link"><span class="function-syntax">DefaultLanguage::get</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nl</span><span class="plain-syntax">));</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="2-tai.html#SP1" class="function-link"><span class="function-syntax">Inflect::suffix</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">plural_trie</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<nav role="progress"><div class="progresscontainer">
    <ul class="progressbar"><li class="progressprev"><a href="2-pp.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-im.html">1</a></li><li class="progresscurrentchapter">2</li><li class="progresssection"><a href="2-tai.html">tai</a></li><li class="progresssection"><a href="2-ai.html">ai</a></li><li class="progresssection"><a href="2-ga.html">ga</a></li><li class="progresssection"><a href="2-pp.html">pp</a></li><li class="progresscurrent">plr</li><li class="progresschapter"><a href="3-lc.html">3</a></li><li class="progresschapter"><a href="4-dl.html">4</a></li><li class="progressnext"><a href="3-lc.html">&#10095;</a></li></ul></div>
</nav><!-- End of weave -->

		</main>
	</body>
</html>

